/****************************************************************************
 *
 * Copyright (C) 2003-2008 Los Alamos National Security, LLC
 *                         Packet Analytics Corporation
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License Version 2 as
 * published by the Free Software Foundation.  You may not use, modify or
 * distribute this program under any other version of the GNU General
 * Public License.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 *
 ****************************************************************************/
package nfse;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Properties;
import java.util.Vector;

import nfse.dataset.netsensor.NetSensorStateMapping;
import nfse.gui.server.DefaultIPLinkFactory;
import nfse.gui.server.GUIRecordFactory;
import nfse.gui.server.IPLinkFactory;
import nfse.gui.server.User;

import org.acegisecurity.GrantedAuthorityImpl;

/*******************************************************************************
 * Convinience class and constant definitions for the NetFSE/Net/FSE codebase.
 * 
 * 
 * @author Ben Uphoff
 * 
 *         This code is the property of Los Alamos National Laboratory and the
 *         University of California, Copyright 2005
 */
public abstract class NetFSE {

    /***************************************************************************
     * Default database name for the alerts database
     */
    public static String ALERT_DB_DATABASE = "alerts";

    /***************************************************************************
     * Default server for the alerts database
     */
    public static String ALERT_DB_HOST = "localhost";

    /***************************************************************************
     * Default password for the alert database
     */
    public static String ALERT_DB_PASSWORD = "NetFSEySQL";

    /***************************************************************************
     * Default user name for the alert database
     */
    public static String ALERT_DB_USER = "root";

    /***************************************************************************
     * Default host for the alert server
     */
    public static String ALERT_SERVER_HOST = "localhost";

    /***************************************************************************
     * Default TCP port for the stats server
     */
    public static int ALERT_SERVER_PORT = 9093;

    /*****
     * Determines if the AutoMigrate process should be started or not.
     */
    public static boolean AUTO_MIGRATE = true;

    public static int AUTO_MIGRATE_NUM_DAYS = 1000;

    public static int AUTO_MIGRATE_NUM_DELETE_DAYS = -1;

    public static int AUTO_MIGRATE_MIN = 3;

    public static int AUTO_MIGRATE_MAX = 100;

    /*****
     * Determines if the AutoQuery process should be started or not.
     */
    public static boolean AUTO_QUERY = true;

    public static int AUTO_STATS_DELETE_DAYS = 7;

    /***************************************************************************
     * Location of the configuration file needed to run the NetFSE server
     */
    public static String CONFIG_FILE = "";

    public static String NODE_CONFIG_FILE = "";

    /***************************************************************************
     * Database connection to the system meta-database server
     */
    public static Connection connection = null;

    /***************************************************************************
     * Default TCP port for the control server
     */
    public static int CONTROL_SERVER_PORT = 9099;

    /*****
     * Determines if the DataFileMonitorLauncher process should be started or
     * not.
     */
    public static boolean DATA_FILE_MONITOR = true;

    /***************************************************************************
     * Default host for the data server
     */
    public static String DATA_SERVER_HOST = "localhost";

    /***************************************************************************
     * Default TCP port for the data server
     */
    public static int DATA_SERVER_PORT = 9097;

    /***************************************************************************
     * Password for dynamic databases used by nfse.DataSocket
     */
    public static String DYNAMIC_DB_PASSWORD = "";

    /***************************************************************************
     * User for dynamic databases used by nfse.DataSocket
     */
    public static String DYNAMIC_DB_USER = "root";

    public static String EMAIL_NOTIFY = "";

    public static String EMAIL_SENDER = "";

    public static String EMAIL_SERVER = "";

    public static final int FIELD_BYTES = 13;

    /***************************************************************************
     * Field identifier for bytes sent by the destination host (i.e. destination
     * bytes)
     */
    public static final int FIELD_DST_BYTES = 7;

    /***************************************************************************
     * Field identifier for destination IP addresses
     */
    public static final int FIELD_DST_IP = 1;

    /***************************************************************************
     * Field identifier for packets sent by the destination host (i.e.
     * destination packets)
     */
    public static final int FIELD_DST_PKTS = 9;

    /***************************************************************************
     * Field identifier for TCP port use by destination host (i.e. destination
     * port)
     */
    public static final int FIELD_DST_PORT = 3;

    /***************************************************************************
     * Field identifier for record durations
     */
    public static final int FIELD_DURATION = 11;

    /***************************************************************************
     * Field identifier for end timestamp
     */
    public static final int FIELD_END_TS = 5;

    public static int[] FIELD_LENGTHS = { 0, 8, 8, 4, 8, 8, 4, 8, 8, 8, 8, 8, 2, 8, 8 };

    /***************************************************************************
     * Array of String objects mapping the names of fields to the field
     * identifier (e.g. NetForSE.FIELD_NAMES[NetForSE.FIELD_SRC_PKTS] is the
     * String "srcpkts")
     */
    public static String[] FIELD_NAMES = { "", "dstip", "srcip", "dstport", "startts", "endts", "srcport", "dstbytes",
            "srcbytes", "dstpkts", "srcpkts", "duration", "protocol", "bytes", "pkts" };

    public static final int FIELD_PACKETS = 14;

    /***************************************************************************
     * Field identifier for IP protocol
     */
    public static final int FIELD_PROTOCOL = 12;

    /***************************************************************************
     * Field identifier for bytes sent by the source host (i.e. source bytes)
     */
    public static final int FIELD_SRC_BYTES = 8;

    /***************************************************************************
     * Field identifier for destination IP addresses
     */
    public static final int FIELD_SRC_IP = 2;

    /***************************************************************************
     * Field identifier for packets sent by the source host (i.e. source
     * packets)
     */
    public static final int FIELD_SRC_PKTS = 10;

    /***************************************************************************
     * Field identifier for TCP port use by source host (i.e. source port)
     */
    public static final int FIELD_SRC_PORT = 6;

    /***************************************************************************
     * Field identifier for start timestamp
     */
    public static final int FIELD_START_TS = 4;

    /***************************************************************************
     * The home network IP/CIDR, used in Net/Sensor processing.
     */
    public static int HOME_CIDR = 24;

    /***************************************************************************
     * The home network IP/CIDR, used in Net/Sensor processing.
     */
    public static String HOME_NETWORK = "";

    public static IPLinkFactory IP_LINK_FACTORY = new DefaultIPLinkFactory();

    /***************************************************************************
     * Local host name for the interface running the Net/FSE server
     */
    public static String LOCAL_HOST = "localhost";

    /***************************************************************************
     * Local IP address for the interface running the Net/FSE server
     */
    public static String LOCAL_IP_ADDRESS = "127.0.0.1";

    /***************************************************************************
     * The path to the location where the NetFSE log files will be stored
     */
    public static String LOG_DIR = "";

    /***************************************************************************
     * This switch is used to start various services in the NetFSEServer if the
     * value is 'true'. This value is set during config file processing.
     */
    public static boolean MASTER = false;

    /***************************************************************************
     * Default server for the system meta-database
     */
    public static String METADATA_DATABASE = "metadata";

    /***************************************************************************
     * Default server for the system meta-database
     */
    public static String METADATA_HOST = "localhost";

    /***************************************************************************
     * Default password for the system meta-database
     */
    public static String METADATA_PASSWORD = "NetFSEySQL";

    /***************************************************************************
     * Default user name for the system meta-database
     */
    public static String METADATA_USER = "root";

    /***************************************************************************
     * Array of String objects mapping month abbreviations to a month number
     * 0-11 (e.g. NetForSE.MONTH_ABBRS[3] is the String "Apr")
     */
    public static String[] MONTH_ABBRS = { "Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov",
            "Dec" };

    /***************************************************************************
     * Upper case month abbreviations
     */
    private static String[] MONTH_ABBRS_UC = { "JAN", "FEB", "MAR", "APR", "MAY", "JUN", "JUL", "AUG", "SEP", "OCT",
            "NOV", "DEC" };

    /*****
     * Determines if the NetFlow listener processes should be started or not.
     */
    public static boolean NET_FLOW = true;

    /*****
     * Determines if the NetListenerServer process should be started or not.
     */
    public static boolean NET_LISTENER = true;

    /***************************************************************************
     * Default TCP port for the Net/Listener server
     */
    public static int NET_LISTENER_SERVER_PORT = 9094;

    /***************************************************************************
     * The path to the directory where nfcapd stores incoming NetFlow records
     */
    public static String NETFLOW_BASE = "/var/log/netflow/";

    /***************************************************************************
     * The path to the nfcapd (NetFlow collector) binary
     */
    public static String NETFLOW_NFCAPD = "/usr/local/bin/nfcapd";

    /***************************************************************************
     * The path to the nfdump (NetFlow print) binary
     */
    public static String NETFLOW_NFDUMP = "/usr/local/bin/nfdump";

    /***************************************************************************
     * Net/Sensor records have state values that are mapped to text strings
     * using this instance.
     */
    public static NetSensorStateMapping netSensorStates = null;

    /***************************************************************************
     * Local node identifier for the interface running the Net/FSE server
     */
    public static int NODE_ID = -1;

    /***************************************************************************
     * Switch for turning on IP address obfuscation, not currently in use.
     */
    public static boolean OBFUSCATE = false;

    /***************************************************************************
     * The predicate identifier for equality (=)
     */
    public static final int PREDICATE_EQUAL_TO = 1;

    /***************************************************************************
     * The predicate identifier for >
     */
    public static final int PREDICATE_GREATER_THAN = 5;

    /***************************************************************************
     * The predicate identifier for >=
     */
    public static final int PREDICATE_GREATER_THAN_EQUAL_TO = 3;

    /***************************************************************************
     * The predicate identifier for <
     */
    public static final int PREDICATE_LESS_THAN = 4;

    /***************************************************************************
     * The predicate identifier for <=
     */
    public static final int PREDICATE_LESS_THAN_EQUAL_TO = 2;

    /***************************************************************************
     * The predicate identifier for range searches
     */
    public static final int PREDICATE_RANGE = 6;

    /***************************************************************************
     * Array of String objects mapping predicate symbols to predicate
     * identifiers (e.g. NetForSE.PREDICATE_NAMES[NetForSE.PREDICATE_RANGE] is
     * the String "~")
     */
    public static String[] PREDICATES = { " ", "=", "<=", ">=", "<", ">", "~" };

    /**
     * The command to execute when running various command line PostgreSQL
     * functions.
     */
    public static String PSQL = "psql";

    /**
     * Command to execute when running pg_dump in BackupPostgreSQL.
     */
    public static String PG_DUMP = "pg_dump";

    /**
     * The home directory of the PostgreSQL database. This is used by
     * DiskManager in determining the % full of the partition containing the
     * PostgreSQL database.
     */
    public static String POSTGRESQL_HOME = "/var/lib/psql";

    /***************************************************************************
     * Default host for the query server
     */
    public static String QUERY_SERVER_HOST = "localhost";

    /***************************************************************************
     * Default TCP port for the query server
     */
    public static int QUERY_SERVER_PORT = 9096;

    /***************************************************************************
     * Database where search results should be stored. Typically 'results'.
     */
    public static String RESULT_DB_DATABASE = "results";

    /***************************************************************************
     * Host where search results should be stored (location of 'results'
     * database). Typically 'localhost'.
     */
    public static String RESULT_DB_HOST = "localhost";

    /***************************************************************************
     * Password for the 'results' database.
     */
    public static String RESULT_DB_PASSWORD = "NetFSEySQL";

    /***************************************************************************
     * User for the 'results' database.
     */
    public static String RESULT_DB_USER = "root";

    /***************************************************************************
     * Flag value indicating that a query result has completed
     */
    public static final int RESULT_SERVER_FLAG_DONE = 1;

    /***************************************************************************
     * Default TCP port for the result server
     */
    public static int RESULT_SERVER_PORT = 9098;

    /***************************************************************************
     * A value used to set a socket's receive buffer
     */
    public static final int SOCKET_RECV_SIZE = 65000;

    /***************************************************************************
     * A value used to set a socket's send buffer
     */
    public static final int SOCKET_SEND_SIZE = 65000;

    /*****
     * Determines if the StatsServer process should be started or not.
     */
    public static boolean STATS = true;

    public static String STATS_DB_DATABASE = "stats";

    public static String STATS_DB_HOST = "localhost";

    public static String STATS_DB_PASSWORD = "NetFSEySQL";

    public static int STATS_DB_PORT = 3306;

    public static String STATS_DB_USER = "root";

    /***************************************************************************
     * Default host for the stats server
     */
    public static String STATS_SERVER_HOST = "localhost";

    /***************************************************************************
     * Default TCP port for the stats server
     */
    public static int STATS_SERVER_PORT = 9095;

    /*****
     * Determines if the Syslog process should be started or not.
     */
    public static boolean SYSLOG = true;

    public static int SYSLOG_PORT = 514;

    public static String SYSLOG_SERVER = "127.0.0.1";

    /*****
     * Determines if the TempDBDelete process should be started or not.
     */
    public static boolean TEMP_DB_DELETE = true;

    /***************************************************************************
     * The frequency when the TempDBDelete process is run, in hours.
     */
    public static int TEMP_DB_DELETE_HOURS = 168;

    /***************************************************************************
     * The temp dir for misc functions
     */
    public static String TEMP_DIR = System.getProperty("java.io.tmpdir");

    /***************************************************************************
     * The maximum number of records to store in a database in nfse.DataSocket.
     */
    public static int TEMP_TABLE_SIZE = 1000000;

    /***************************************************************************
     * Default type used to specify the inclusion of all types in a query
     */
    public static final int TYPE_ALL = 0;

    /***************************************************************************
     * Maps type IDs (keys) to type class names (fully qualified class names).
     */
    public static HashMap<Integer, String> TYPE_CLASS_NAMES = null;

    /***************************************************************************
     * Maps type IDs (keys) to type instances (subclasses of nfse.NetFSERecord).
     */
    public static HashMap<Integer, NetFSERecord> TYPE_CLASSES = null;

    /***************************************************************************
     * Maps type IDs (keys) to type names.
     */
    private static HashMap<Integer, String> TYPE_NAMES = null;

    /***************************************************************************
     * Flag specifying whether or not to use SSL sockets for receiving records
     * from a data client
     */
    public static boolean USE_SSL_DATA = false;

    /***************************************************************************
     * Flag specifying whether or not to use SSL sockets for query operations
     */
    public static boolean USE_SSL_QUERY = false;

    /***************************************************************************
     * Flag specifying whether or not to use SSL sockets for sending results to
     * a client
     */
    public static boolean USE_SSL_RESULT = false;

    private static int DYNAMIC_DB_PORT = 5432;

    public static int RESULT_DB_PORT = 5432;

    private static int METADATA_PORT = 5432;

    public static Connection createLocalDatabaseConnection(String databaseName) throws Exception {
        Class.forName("org.postgresql.Driver");
        Properties props = new Properties();
        props.setProperty("user", NetFSE.DYNAMIC_DB_USER);
        props.setProperty("password", NetFSE.DYNAMIC_DB_PASSWORD);
        props.setProperty("client_encoding", "SQL_ASCII");

        Class.forName("org.postgresql.Driver");
        String url = "jdbc:postgresql://" + NetFSE.LOCAL_HOST + ":" + NetFSE.DYNAMIC_DB_PORT + "/"
                + databaseName.toLowerCase();
        // System.out.println(url);
        Connection connection = DriverManager.getConnection(url, props);

        return connection;
    }

    public static synchronized void configure() throws Exception {

        String configFile = System.getProperty("nfse.configfile");
        if (configFile == null)
            throw new Exception(
                    "Property to config file not set. Set nfse.configfile before calling NetFSE.configure().");

        Connection connection = null;
        Statement s = null;

        LineNumberReader in = new LineNumberReader(new FileReader(configFile));
        String line = in.readLine();
        // System.out.println(line);
        while (line != null) {
            // System.out.println(line);
            String[] tokens = line.split(" ");
            if (tokens[0].equals("Metadata::password")) {
                NetFSE.METADATA_PASSWORD = tokens[1].trim();
            } else if (tokens[0].equals("Metadata::user")) {
                NetFSE.METADATA_USER = tokens[1].trim();
            } else if (tokens[0].equals("Metadata::host")) {
                NetFSE.METADATA_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Metadata::database")) {
                NetFSE.METADATA_DATABASE = tokens[1].trim();
            } else if (tokens[0].equals("Metadata::port")) {
                NetFSE.METADATA_PORT = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("Master")) {
                if (tokens[1].equals("true")) {
                    NetFSE.MASTER = true;
                } else {
                    NetFSE.MASTER = false;
                }
            } else if (tokens[0].equals("NodeConfig")) {
                NetFSE.NODE_CONFIG_FILE = tokens[1];
                NetFSE.processNodeConfigFile(new File(NetFSE.NODE_CONFIG_FILE));
            }
            line = in.readLine();
        }

        Properties props = new Properties();
        props.setProperty("user", METADATA_USER);
        props.setProperty("password", METADATA_PASSWORD);
        props.setProperty("client_encoding", "UTF8");

        Class.forName("org.postgresql.Driver");
        String url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + ":" + NetFSE.METADATA_PORT + "/"
                + NetFSE.METADATA_DATABASE;
        connection = DriverManager.getConnection(url, props);
        s = connection.createStatement();

        if (NetFSE.MASTER) {
            s.execute("delete from Type_Classes");
            s.execute("delete from Tools");
            s.execute("delete from app_list");
            s.execute("delete from nodes");
        }

        in = new LineNumberReader(new FileReader(configFile));
        line = in.readLine();

        // System.out.println(line);
        while (line != null) {
            // System.out.println(line);
            String[] tokens = line.split(" ");
            if (tokens[0].equals("Dynamic::password")) {
                NetFSE.DYNAMIC_DB_PASSWORD = tokens[1].trim();
            } else if (tokens[0].equals("Dynamic::user")) {
                NetFSE.DYNAMIC_DB_USER = tokens[1].trim();
            } else if (tokens[0].equals("Dynamic::port")) {
                NetFSE.DYNAMIC_DB_PORT = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("Result::password")) {
                NetFSE.RESULT_DB_PASSWORD = tokens[1].trim();
            } else if (tokens[0].equals("Result::user")) {
                NetFSE.RESULT_DB_USER = tokens[1].trim();
            } else if (tokens[0].equals("Result::host")) {
                NetFSE.RESULT_DB_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Result::database")) {
                NetFSE.RESULT_DB_DATABASE = tokens[1].trim();
            } else if (tokens[0].equals("Result::port")) {
                NetFSE.RESULT_DB_PORT = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("Stats::password")) {
                NetFSE.STATS_DB_PASSWORD = tokens[1].trim();
            } else if (tokens[0].equals("Stats::user")) {
                NetFSE.STATS_DB_USER = tokens[1].trim();
            } else if (tokens[0].equals("Stats::host")) {
                NetFSE.STATS_DB_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Stats::database")) {
                NetFSE.STATS_DB_DATABASE = tokens[1].trim();
            } else if (tokens[0].equals("Alerts::password")) {
                NetFSE.ALERT_DB_PASSWORD = tokens[1].trim();
            } else if (tokens[0].equals("Alerts::user")) {
                NetFSE.ALERT_DB_USER = tokens[1].trim();
            } else if (tokens[0].equals("Alerts::host")) {
                NetFSE.ALERT_DB_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Alerts::database")) {
                NetFSE.ALERT_DB_DATABASE = tokens[1].trim();
            } else if (tokens[0].equals("Obfuscate")) {
                if (tokens[1].equals("true")) {
                    NetFSE.OBFUSCATE = true;
                } else {
                    NetFSE.OBFUSCATE = false;
                }
            } else if (tokens[0].equals("PSQL")) {
                NetFSE.PSQL = "";
                for (int i = 1; i < tokens.length; i++)
                    NetFSE.PSQL += tokens[i] + " ";
                NetFSE.PSQL = NetFSE.PSQL.trim();
            } else if (tokens[0].equals("POSTGRESQL_HOME")) {
                NetFSE.POSTGRESQL_HOME = tokens[1].trim();
            } else if (tokens[0].equals("PG_DUMP")) {
                NetFSE.PG_DUMP = "";
                for (int i = 1; i < tokens.length; i++)
                    NetFSE.PG_DUMP += tokens[i] + " ";
                NetFSE.PG_DUMP = NetFSE.PG_DUMP.trim();
            } else if (tokens[0].equals("HomeNetwork")) {
                String[] tokens2 = tokens[1].split("/");
                NetFSE.HOME_NETWORK = tokens2[0];
                NetFSE.HOME_CIDR = Integer.parseInt(tokens2[1]);
            } else if (tokens[0].equals("Log ")) {
                NetFSE.LOG_DIR = tokens[1].trim();
            } else if (tokens[0].equals("TempTableSize")) {
                try {
                    NetFSE.TEMP_TABLE_SIZE = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("AutoStatsDeleteDays")) {
                try {
                    NetFSE.AUTO_STATS_DELETE_DAYS = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Email::from")) {
                NetFSE.EMAIL_SENDER = tokens[1].trim();
            } else if (tokens[0].equals("Email::to")) {
                NetFSE.EMAIL_NOTIFY = tokens[1].trim();
            } else if (tokens[0].equals("Email::server")) {
                NetFSE.EMAIL_SERVER = tokens[1].trim();
            } else if (tokens[0].equals("Syslog::server")) {
                NetFSE.SYSLOG_SERVER = tokens[1].trim();
            } else if (tokens[0].equals("Syslog::port")) {
                NetFSE.SYSLOG_PORT = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("Server::queryhost")) {
                NetFSE.QUERY_SERVER_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Server::datahost")) {
                NetFSE.DATA_SERVER_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Server::statshost")) {
                NetFSE.STATS_SERVER_HOST = tokens[1].trim();
            } else if (tokens[0].equals("Server::tempdir")) {
                NetFSE.TEMP_DIR = tokens[1].trim();
                File tempDir = new File(NetFSE.TEMP_DIR);
                if (!tempDir.exists())
                    tempDir.mkdirs();
                else if (!tempDir.isDirectory())
                    throw new IOException("Invalid temp dir specified: " + tempDir.getAbsolutePath()
                            + "is a file, not a directory.");
            } else if (tokens[0].equals("Server::listenerport")) {
                try {
                    NetFSE.NET_LISTENER_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Server::queryport")) {
                try {
                    NetFSE.QUERY_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Server::dataport")) {
                try {
                    NetFSE.DATA_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Server::statsport")) {
                try {
                    NetFSE.STATS_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Server::resultport")) {
                try {
                    NetFSE.RESULT_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("Server::controlport")) {
                try {
                    NetFSE.CONTROL_SERVER_PORT = Integer.parseInt(tokens[1].trim());
                } catch (Exception E) {
                    E.printStackTrace();
                }
            } else if (tokens[0].equals("TempDBDelete::hours")) {
                NetFSE.TEMP_DB_DELETE_HOURS = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("NetFlow::nfdump")) {
                NetFSE.NETFLOW_NFDUMP = tokens[1];
            } else if (tokens[0].equals("NetFlow:nfcapd")) {
                NetFSE.NETFLOW_NFCAPD = tokens[1];
            } else if (tokens[0].equals("NetFlow::base")) {
                NetFSE.NETFLOW_BASE = tokens[1];
            } else if (tokens[0].equals("TempDBDelete::hours")) {
                NetFSE.TEMP_DB_DELETE_HOURS = Integer.parseInt(tokens[1].trim());
            } else if (tokens[0].equals("Type::class") && NetFSE.MASTER) {
                String className = tokens[1];
                NetFSERecord rec = (NetFSERecord) Class.forName(className).newInstance();
                int id = Integer.parseInt(tokens[2]);
                String name = tokens[3];
                rec.setTypeID(id);
                rec.setTypeName(name);

                // try {

                // s.execute("delete from Type_Classes where Type_ID=" +
                // id);
                s.execute("insert into Type_Classes values (" + id + ",'" + className + "','" + name + "')");
                try {
                    s.execute("create database " + className + " encoding='SQL_ASCII'");
                } catch (Exception e) {

                }
                try {
                    // s.execute("delete from Tools where ID=" + id);
                    s.execute("insert into Tools values (" + id + ",'" + name + "','')");
                } catch (Exception e) {

                }

                // } catch (Exception e) {
                // e.printStackTrace();
                // }

            } else if (tokens[0].equals("Node") && NetFSE.MASTER) {
                // Entries of the form: Node ID IP {build: 1 or 0} {query: 1
                // or 0} dynamic_db_user dynamic_db_password
                // data_server_port

                int id = Integer.parseInt(tokens[1]);
                String ip = tokens[2];
                int build = Integer.parseInt(tokens[3]);
                int query = Integer.parseInt(tokens[4]);
                String dynamicDBUser = tokens[5];
                String dynamicDBPassword = tokens[6];
                int dynamicDBPort = Integer.parseInt(tokens[7]);
                int dataServerPort = Integer.parseInt(tokens[8]);

                // s.execute("delete from Nodes where ID=" + id);
                s.execute("insert into Nodes values (" + id + ",'" + ip + "'," + build + "," + query + ",'"
                        + dynamicDBUser + "','" + dynamicDBPassword + "'" + "," + dynamicDBPort + "," + dataServerPort
                        + ")");

            } else if (tokens[0].equals("App") && NetFSE.MASTER) {
                // Entries of the form: App ID class_name type1, type2, ..,
                // typeN

                int id = Integer.parseInt(tokens[1]);
                int nodeID = Integer.parseInt(tokens[2]);
                String app = tokens[3];

                // This will eventually be used to be able to define certain
                // apps to run against particular types of data
                int[] types = new int[tokens.length - 4];
                for (int i = 0; i < types.length; i++) {
                    types[i] = Integer.parseInt(tokens[i + 4]);
                }

                // s.execute("delete from app_list where app_id=" + id);
                s.execute("insert into app_list values (" + id + "," + nodeID + ",'" + app + "','" + app + "')");

            } else if (tokens[0].equals("AutoMigrate")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.AUTO_MIGRATE = false;
                }
            } else if (tokens[0].equals("AutoMigrate::days")) {
                NetFSE.AUTO_MIGRATE_NUM_DAYS = Integer.parseInt(tokens[1]);
            } else if (tokens[0].equals("AutoMigrate::deletedays")) {
                NetFSE.AUTO_MIGRATE_NUM_DELETE_DAYS = Integer.parseInt(tokens[1]);
            } else if (tokens[0].equals("AutoMigrate::min")) {
                NetFSE.AUTO_MIGRATE_MIN = Integer.parseInt(tokens[1]);
            } else if (tokens[0].equals("AutoMigrate::max")) {
                NetFSE.AUTO_MIGRATE_MAX = Integer.parseInt(tokens[1]);
            } else if (tokens[0].equals("NetListener")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.NET_LISTENER = false;
                }
            } else if (tokens[0].equals("NetFlow")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.NET_FLOW = false;
                }
            } else if (tokens[0].equals("Syslog")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.SYSLOG = false;
                }
            } else if (tokens[0].equals("AutoQuery")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.AUTO_QUERY = false;
                }
            } else if (tokens[0].equals("TempDBDelete")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.TEMP_DB_DELETE = false;
                }
            } else if (tokens[0].equals("Stats")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.STATS = false;
                }
            } else if (tokens[0].equals("DataFileMonitor")) {
                if (tokens[1].toLowerCase().equals("off")) {
                    NetFSE.DATA_FILE_MONITOR = false;
                }
            } else if (tokens[0].equals("WebInterface::iplinkfactory")) {
                NetFSE.IP_LINK_FACTORY = (IPLinkFactory) Class.forName(tokens[1]).newInstance();
                NetFSE.IP_LINK_FACTORY.init();
            }
            line = in.readLine();
        }
        in.close();
        if (s != null) {
            s.close();
            connection.close();
        }

        if (NetFSE.TYPE_CLASS_NAMES != null)
            return;

        NetFSE.TYPE_CLASS_NAMES = new HashMap<Integer, String>();
        NetFSE.TYPE_CLASSES = new HashMap<Integer, NetFSERecord>();
        NetFSE.TYPE_NAMES = new HashMap<Integer, String>();
        NetFSE.TYPE_NAMES.put(0, "All");

        try {
            props = new Properties();
            props.setProperty("user", METADATA_USER);
            props.setProperty("password", METADATA_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            Class.forName("org.postgresql.Driver");
            url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + "/" + NetFSE.METADATA_DATABASE;
            connection = DriverManager.getConnection(url, props);
            s = connection.createStatement();
            ResultSet rs = s.executeQuery("select * from Type_Classes");
            while (rs.next()) {
                String className = rs.getString("Class_Name");
                String typeName = rs.getString("Type_Name");
                int typeID = rs.getInt("Type_ID");
                NetFSERecord rec = (NetFSERecord) Class.forName(className).newInstance();
                rec.setTypeID(typeID);
                rec.setTypeName(typeName);
                int id = rec.getTypeID();

                NetFSE.TYPE_NAMES.put(new Integer(id), typeName);
                NetFSE.TYPE_CLASS_NAMES.put(new Integer(id), className);
                NetFSE.TYPE_CLASSES.put(new Integer(id), rec);

            }
            rs.close();
            s.close();
            connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        s = null;
        try {
            s = NetFSE.createStatement();
            netSensorStates = new NetSensorStateMapping();
            netSensorStates.init(s);
            s.close();
        } catch (Exception e) {
            e.printStackTrace();
            try {
                s.close();
            } catch (Exception e2) {

            }
        }

    }

    private synchronized static Statement createStatement() throws Exception {
        if (connection == null)
            NetFSE.initializeConnection();

        Statement s = null;
        try {
            s = connection.createStatement();
        } catch (Exception e) {
            e.printStackTrace();
            NetFSE.initializeConnection();
            s = connection.createStatement();
        }
        return s;
    }

    /***************************************************************************
     * Gets the status of all nodes in the system that have a build task. May be
     * depreciated.
     * 
     * @return An array of NodeStatus objects or an empty (non-null) array on
     *         error
     */
    public static NodeStatus[] getBuildNodeStatus() {
        String sql = "select * from Nodes where Build != 0";
        return nodeStatus(sql);
    }

    /***************************************************************************
     * Gets the status of all nodes in the system that have a task associated
     * with the given sensor.
     * 
     * @param sensor
     *            The sensor ID for which to obtain node status information
     * @return An array of NodeStatus objects or an empty (non-null) array on
     *         error
     */
    public static NodeStatus[] getBuildNodeStatusBySensor(int sensor) {
        // Disabled the Node_Tasks feature for now, just return all build nodes
        return getBuildNodeStatus();

        // String sql = "select * from Nodes, Node_Tasks where Nodes.Build != 0
        // and Nodes.ID=Node_Tasks.Node_ID and Node_Tasks.Sensor_ID="
        // + sensor + " and Node_Tasks.Task_Type=" + NetFSE.TASK_BUILD;
        // return nodeStatus(sql);
    }

    public static double getDiskFullPercent(String path) throws Exception {
        if (!path.endsWith("/"))
            path += "/";
        File file = new File(path);
        long free = file.getFreeSpace();
        long total = file.getTotalSpace();
        double percentFull = (((double) total-free) / (double) total) * 100.0;
        return percentFull;

        /*
         * float val = -1.0f; float rootVal = -1.0f; Process p =
         * Runtime.getRuntime().exec("df " + path); BufferedReader br = new
         * BufferedReader(new InputStreamReader(p.getInputStream())); int
         * lineCount = 0; String line = null; int maxLen = -1; while ((line =
         * br.readLine()) != null) {
         * 
         * String[] result = line.split("\\s+"); // LineCount = 0 is the header.
         * Skip header if ((result.length == 6) && lineCount != 0) { String dir
         * = result[5] + "/";
         * 
         * long spaceUsed = Long.parseLong(result[2]); long spaceAvailable =
         * Long.parseLong(result[1]); float tempVal = (float) (((double)
         * spaceUsed / (double) spaceAvailable) * 100.0d); if (path.equals(dir))
         * { val = tempVal; break; } else if (path.startsWith(dir) && (maxLen ==
         * -1 || dir.length() > maxLen)) { val = tempVal; //
         * System.out.println("VAL=" + val); maxLen = dir.length(); } else if
         * (dir.equals("//")) { rootVal = tempVal; } } lineCount++;
         * 
         * } if (val == -1.0f) { val = rootVal; } try { br.close();
         * p.getErrorStream().close(); p.getInputStream().close();
         * p.getOutputStream().close(); p.destroy(); } catch (Exception E) {
         * E.printStackTrace(); }
         * 
         * return val;
         */
    }

    public static int getFieldLength(int id) {
        return FIELD_LENGTHS[id];
    }

    /***************************************************************************
     * Given a field identifier, returns the name of that field.
     * 
     * @param field
     *            The field identifier from the system metadata
     * @return The field name
     */
    public static String getFieldName(int field) {
        if ((field <= 0) && (field > FIELD_NAMES.length))
            return "unknown";
        return FIELD_NAMES[field];
    }

    /***************************************************************************
     * Given a field name, returns the identifier of that field.
     * 
     * @param field
     *            The field name from the system metadata
     * @return The identifier of the field from the system metadata
     */
    public static int getFieldType(String field) {
        for (int i = 1; i < FIELD_NAMES.length; i++) {
            if (FIELD_NAMES[i].compareTo(field) == 0)
                return i;
        }
        return -1;
    }

    /***************************************************************************
     * Given a global field identifier, returns the field information from the
     * system metadata.
     * 
     * @param globalFieldID
     *            The field identifier for which to obtain field information
     * @return A GlobalField object or null on error
     */
    public static GlobalField getGlobalField(int globalFieldID) {
        return NetFSE.getGlobalField(NetFSE.FIELD_NAMES[globalFieldID]);
    }

    public static GlobalField getGlobalField(String globalFieldName) {
        try {
            GlobalField temp = new GlobalField();
            temp.setName(globalFieldName);
            temp.setId(NetFSE.getFieldType(globalFieldName));
            temp.setLength(NetFSE.getFieldLength(temp.getId()));
            return temp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***************************************************************************
     * Given a month abbreviation, returns the month number (1-12).
     * 
     * @param abbr
     *            The three letter month abbreviation
     * @return The number of the month (1-12)
     */
    public static int getMonthValue(String abbr) {
        abbr = abbr.toUpperCase();
        int month = -1;
        for (int i = 0; i < MONTH_ABBRS_UC.length; i++) {
            if (abbr.equals(MONTH_ABBRS_UC[i])) {
                month = i + 1;
                break;
            }
        }
        return month;
    }

    /***************************************************************************
     * Gets the status of all nodes in the system.
     * 
     * @return An array of NodeStatus objects indicating the state of nodes in
     *         the system or an empty (non-null) array on error
     */
    public static NodeStatus[] getNodeStatus() {
        String sql = "select * from Nodes";
        return nodeStatus(sql);
    }

    /***************************************************************************
     * Gets the status of a particular node in the system by system ID.
     * 
     * @param nodeID
     *            Unique system identfier of the node for which to obtain status
     *            inofmration
     * @return The status of node or a null if there was an error
     */
    public static NodeStatus getNodeStatus(int nodeID) {
        String sql = "Select * from Nodes where ID = " + nodeID;
        NodeStatus[] status = nodeStatus(sql);
        if ((status == null) || (status.length == 0))
            return null;
        return status[0];
    }

    /***************************************************************************
     * Gets the status of a particular node in the system by name.
     * 
     * @param nodeName
     *            Name of the node for which to obtain status inofmration
     * @return The status of node or a null if there was an error
     */
    public static NodeStatus getNodeStatus(String nodeName) {
        String sql = "Select * from Nodes where Name = '" + nodeName + "'";
        NodeStatus[] status = nodeStatus(sql);
        if ((status == null) || (status.length == 0))
            return null;
        return status[0];
    }

    public static double getPostgresDiskFullPercent() throws Exception {
        String psqlDir = NetFSE.POSTGRESQL_HOME;
        return getDiskFullPercent(psqlDir);
    }

    /***************************************************************************
     * Given a predicate string, returns the identifier of that predicate.
     * 
     * @param predicate
     *            The predicate string from the system metadata
     * @return The identifier of the predicate from the system metadata
     */
    public static int getPredicate(String predicate) {
        for (int i = 0; i < PREDICATES.length; i++)
            if (PREDICATES[i].compareTo(predicate) == 0)
                return i;
        return -1;
    }

    /***************************************************************************
     * Given a predicate identifier, returns the name of that predicate.
     * 
     * @param predicate
     *            The predicate identifier from the system metadata
     * @return The string representation of the predicate
     */
    public static String getPredicateName(int predicate) {
        if ((predicate <= 0) && (predicate > PREDICATES.length))
            return " ";
        return PREDICATES[predicate];
    }

    /***************************************************************************
     * Gets the status of all nodes in the system that have a query task. May be
     * depreciated.
     * 
     * @return An array of NodeStatus objects or an empty (non-null) array on
     *         error
     */
    public static NodeStatus[] getQueryNodeStatus() {
        String sql = "select * from Nodes where Query != 0";
        return nodeStatus(sql);
    }

    public static String getSchema(int type) {

        if (NetFSE.TYPE_CLASSES == null) {
            try {
                NetFSE.configure();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        String result = "";
        try {
            NetFSERecordFactory temp = NetFSE.getRecordFactory(type);
            GUIRecordFactory factory = (GUIRecordFactory) temp;
            result = factory.getCreateFieldTableSQL(temp.typeName);
        } catch (Exception e) {
            // no op, not a GUI record
        }
        return result;
    }

    /***************************************************************************
     * Returns a SensorInfo array for all data types in the system metadata.
     * 
     * @return An array of SensorInfo objects or null on error
     */
    public static ArrayList<SensorInfo> getSensorInfo() {
        ArrayList<SensorInfo> temp = new ArrayList<SensorInfo>();
        try {
            Statement statement = NetFSE.createStatement();
            ResultSet rs = statement.executeQuery("select * from Sensors");
            while (rs.next()) {
                SensorInfo ti = new SensorInfo(rs.getInt(1), rs.getInt(2), rs.getString(3));
                temp.add(ti);
            }
            rs.close();
            statement.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return temp;
    }

    /***************************************************************************
     * Returns a SensorInfo object the given ID.
     * 
     * @param sensorID
     *            The sensor identifier for which to obtain information
     * @return A SensorInfo object for or null on error
     */
    public static SensorInfo getSensorInfo(int sensorID) {
        try {
            SensorInfo temp = null;

            Statement statement = NetFSE.createStatement();
            ResultSet rs = statement.executeQuery("select * from Sensors where ID = " + sensorID);
            if (rs.next())
                temp = new SensorInfo(rs.getInt(1), rs.getInt(2), rs.getString(3));
            rs.close();
            statement.close();

            // connection.close();
            return temp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***************************************************************************
     * Returns a ToolInfo array for all data types in the system metadata.
     * 
     * @return An array of ToolInfo objects or null on error
     */
    public static ToolInfo[] getToolInfo() {
        try {
            Vector<ToolInfo> temp = new Vector<ToolInfo>();
            Statement statement = NetFSE.createStatement();
            ResultSet rs = statement.executeQuery("select * from Tools");
            while (rs.next()) {
                ToolInfo ti = new ToolInfo(rs.getInt(1), rs.getString(2), rs.getString(3));
                temp.addElement(ti);
            }
            rs.close();
            statement.close();

            // Build the array to return to caller
            ToolInfo[] info = new ToolInfo[temp.size()];
            for (int i = 0; i < info.length; i++)
                info[i] = (ToolInfo) temp.elementAt(i);
            return info;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    /***************************************************************************
     * Returns a ToolInfo object the given ID.
     * 
     * @param toolID
     *            The tool identifier for which to obtain information
     * @return A ToolInfo object for or null on error
     */
    public static ToolInfo getToolInfo(int toolID) {
        try {
            Statement statement = NetFSE.createStatement();
            ResultSet rs = statement.executeQuery("select * from Tools where ID = " + toolID);
            ToolInfo temp = null;
            if (rs.next())
                temp = new ToolInfo(rs.getInt(1), rs.getString(2), rs.getString(3));
            rs.close();
            statement.close();
            // connection.close();
            return temp;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return null;
    }

    public static NetFSERecord getTypeClass(int type) {
        if (NetFSE.TYPE_CLASSES == null) {
            try {
                NetFSE.configure();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return (NetFSERecord) NetFSE.TYPE_CLASSES.get(new Integer(type));
    }

    public static NetFSERecordFactory getRecordFactory(int type) throws InstantiationException, IllegalAccessException,
            ClassNotFoundException {
        NetFSERecordFactory rec = (NetFSERecordFactory) Class.forName(NetFSE.getTypeClassName(type) + "Factory")
                .newInstance();
        return rec;
    }

    public static String getTypeClassName(int type) {
        if (NetFSE.TYPE_CLASSES == null) {
            try {
                NetFSE.configure();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        String temp = (String) NetFSE.TYPE_CLASS_NAMES.get(new Integer(type));
        return temp;
    }

    public static String getTypeName(int type) {
        if (NetFSE.TYPE_CLASSES == null) {
            try {
                NetFSE.configure();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        String temp = (String) NetFSE.TYPE_NAMES.get(new Integer(type));
        return temp;
    }

    public static String[] getTypeNames() {
        if (NetFSE.TYPE_CLASSES == null) {
            try {
                NetFSE.configure();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        Collection<String> values = NetFSE.TYPE_NAMES.values();
        int count = values.size() - 1;
        String[] temp = new String[count];
        Iterator<String> it = values.iterator();
        int idx = 0;
        while (it.hasNext()) {
            String val = it.next();
            if (!val.equals("All")) {
                temp[idx] = val;
                idx++;
            }
        }
        return temp;
    }

    public static int[] getTypes() {
        try {
            if (NetFSE.TYPE_CLASSES == null)
                NetFSE.configure();
        } catch (Exception e) {
            e.printStackTrace();
        }
        Collection<Integer> keys = NetFSE.TYPE_NAMES.keySet();
        int count = keys.size() - 1;
        int[] temp = new int[count];
        Iterator<Integer> it = keys.iterator();
        int idx = 0;
        while (it.hasNext()) {
            int val = it.next();
            if (val != 0) {
                temp[idx] = val;
                idx++;
            }
        }
        return temp;
    }

    public static User getUser(String userName) {
        User temp = null;

        try {
            Statement s = createStatement();

            String sql = "select * from Users where user_name='" + userName + "'";
            ResultSet rs = s.executeQuery(sql);
            if (rs.next()) {
                GrantedAuthorityImpl[] gas = new GrantedAuthorityImpl[2];
                gas[0] = new GrantedAuthorityImpl("USER_ROLE");
                gas[1] = new GrantedAuthorityImpl("ADMIN_ROLE");
                String password = rs.getString("Password");
                temp = new User(userName, password, true, true, true, true, gas);
            }
            rs.next();
            rs.close();
            s.close();
        } catch (Exception e) {
            e.printStackTrace();
            temp = null;
        }
        return temp;
    }

    /***************************************************************************
     * Returns the user identifier given a user name.
     * 
     * @param user
     *            The user name from the system metadata
     * @return The user identifier from the system metadata
     */
    public static int getUserID(String user) {
        int id = -1;
        try {
            Statement statement = NetFSE.createStatement();
            ResultSet rs = null;
            rs = statement.executeQuery("select * from Users where User_Name='" + user + "'");
            if (rs.next())
                id = rs.getInt("ID");
            rs.close();
            statement.close();
            // connection.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return id;
    }

    /***************************************************************************
     * Opens a connection to the main NetFSE meta-database.
     * 
     */
    public static synchronized void initializeConnection() {
        try {
            try {
                NetFSE.configure();
            } catch (Exception ioe) {
                ioe.printStackTrace();
            }

            Properties props = new Properties();
            props.setProperty("user", METADATA_USER);
            props.setProperty("password", METADATA_PASSWORD);
            props.setProperty("client_encoding", "UTF8");

            Class.forName("org.postgresql.Driver");
            String url = "jdbc:postgresql://" + NetFSE.METADATA_HOST + "/" + NetFSE.METADATA_DATABASE;
            connection = DriverManager.getConnection(url, props);

        } catch (Exception E) {
            E.printStackTrace();
        }
    }

    public static boolean isHomeNet(long ip) {
        return true;

        /*
         * if (HOME_NETWORK_IP_VAL == -1) { HOME_NETWORK_IP_VAL =
         * NetFSEUtil.convertIPtoLong(HOME_NETWORK); }
         * 
         * if ((ip & getCIDRMaskValue(HOME_CIDR)) == HOME_NETWORK_IP_VAL) return
         * true; return false;
         */
    }

    public static boolean isHomeNet(String ip) {

        long ipVal = NetFSEUtil.convertIPtoLong(ip);
        return isHomeNet(ipVal);
    }

    public static boolean isTypeValid(int type) {
        if (type == 0)
            return true;
        if (NetFSE.TYPE_NAMES.get(new Integer(type)) != null)
            return true;
        return false;

    }

    /***************************************************************************
     * Executes the SQL provided and returns the status of nodes in the system.
     * 
     * @param sql
     *            The SQL generated by one of the above public getNodeStatus
     *            methods
     * @return An array of NodeStatus objects indicating the state of nodes in
     *         the system or an empty (non-null) array on error
     */
    private static NodeStatus[] nodeStatus(String sql) {
        /*
         * if (true) { NodeStatus[] temp = new NodeStatus[1]; NodeStatus ns =
         * new NodeStatus(); ns.id = NetFSE.NODE_ID; ns.name = NetFSE.HOST_NAME;
         * ns.build = true; ns.query = true; }
         */

        try {
            Vector<NodeStatus> temp = new Vector<NodeStatus>();

            Statement statement = NetFSE.createStatement();
            ResultSet rs = statement.executeQuery(sql);
            while (rs.next()) {
                NodeStatus ns = new NodeStatus();
                ns.setID(rs.getInt("ID"));
                ns.setName(rs.getString("Name"));
                ns.setBuild(rs.getBoolean("Build"));
                ns.setQuery(rs.getBoolean("Query"));
                ns.setDynamicPassword(rs.getString("Dynamic_DB_Password"));
                ns.setDynamicUser(rs.getString("Dynamic_DB_User"));
                ns.setDataServerPort(rs.getInt("Data_Server_Port"));
                temp.addElement(ns);
                // System.out.println("" + ns.id + ": " + ns.name);
            }
            rs.close();
            statement.close();

            // Build the array to return to the caller
            NodeStatus[] status = new NodeStatus[temp.size()];
            for (int i = 0; i < status.length; i++)
                status[i] = (NodeStatus) temp.elementAt(i);
            return status;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return new NodeStatus[0];
    }

    /***************************************************************************
     * Reads in the nodes file specified in the args.<br>
     * Note: this may become obsolete in future releases.
     * 
     * @param config
     *            The file to process
     * @exception Exception
     *                Any processing error will generate an exception
     */
    public static void processNodeConfigFile(File config) throws Exception {

        LineNumberReader in = new LineNumberReader(new FileReader(config));
        String line = in.readLine();
        while (line != null) {
            if (line.startsWith("IP ")) {
                NetFSE.LOCAL_IP_ADDRESS = line.substring(line.indexOf(' ')).trim();
            } else if (line.startsWith("ID ")) {
                NetFSE.NODE_ID = Integer.parseInt(line.substring(line.indexOf(' ')).trim());
            } else if (line.startsWith("HOST ")) {
                NetFSE.LOCAL_HOST = line.substring(line.indexOf(' ')).trim();
            }
            line = in.readLine();
        }
        in.close();

    }

    public static long getAvailbleGlobalStorage() {
        // TODO Auto-generated method stub
        return 0;
    }

}